package com.example.moneybook.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.moneybook.dto.ResponseResult;
import com.example.moneybook.enums.AppHttpCodeEnum;
import com.example.moneybook.mapper.AccountMapper;
import com.example.moneybook.mapper.BorrowMapper;
import com.example.moneybook.mapper.DetailMapper;
import com.example.moneybook.mapper.TransferMapper;
import com.example.moneybook.pojo.Account;
import com.example.moneybook.pojo.Bill;
import com.example.moneybook.pojo.Borrow;
import com.example.moneybook.pojo.Transfer;
import com.example.moneybook.service.AccountService;
import com.example.moneybook.service.BorrowService;
import com.example.moneybook.service.DetailService;
import com.example.moneybook.service.TransferService;
import com.example.moneybook.vo.TransferVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: 包
 * @Date: 2023/2/24 14:37
 * Description:
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {
    @Autowired
    private AccountMapper accountMapper;


    /**
     * 添加账户
     * @param account
     * @return
     */
    @Override
    public ResponseResult addAccount(Account account) {
        if (account == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        int accountId = getAccountId(account.getUserId(), account.getAccountName());
        if (accountId != 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "账户名重复");
        }
        if (account.getAccountState() == 1){
            account.setAccountMoney(-account.getAccountMoney());
            int res = accountMapper.insert(account);
            if (res == 0){
                return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
            }else {
                return ResponseResult.okResult(200, "添加成功");
            }
        }else {
            int res = accountMapper.insert(account);
            if (res == 0){
                return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
            }else {
                return ResponseResult.okResult(200, "添加成功");
            }
        }

    }

    /**
     * 加载账户资源
     * @param userId
     * @return
     */
    @Override
    public ResponseResult loadAccount(String userId) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        List<Account> accounts = accountMapper.selectList(queryWrapper);
        return ResponseResult.okResult(accounts);
    }

    /**
     * 获取用户账户列表
     * @param userId
     * @return
     */
    @Override
    public ResponseResult getUserAccount(String userId) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("user_id",userId)
                .select("account_name");
        List<Account> accounts = accountMapper.selectList(queryWrapper);
        List<String> accountName = new ArrayList<>();
        for (Account account : accounts) {
            accountName.add(account.getAccountName());
        }
        return ResponseResult.okResult(accountName);
    }

    @Autowired
    private DetailService detailService;
    @Autowired
    private BorrowService borrowService;
    @Autowired
    private TransferService transferService;

    /**
     * 获取账户的账单（收支明细，借款，转账）
     * @param userId
     * @param accountId
     * @param listType 0收支明细，1借款，2转账
     * @return
     */
    @Override
    public ResponseResult loadAccountBill(String userId, int accountId, int listType) {
        if (listType == 0) {
            List<Bill> bills = detailService.detailByAccount(userId, accountId);
            return ResponseResult.okResult(bills);
        }else if (listType == 1){
            List<Borrow> borrows = borrowService.borrowByAccount(userId, accountId);
            return ResponseResult.okResult(borrows);
        }else if (listType == 2){
            List<TransferVo> transfers = transferService.transferByAccount(userId,accountId);
            return ResponseResult.okResult(transfers);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }

    /**
     * 获取账户Id
     * @param userId
     * @param accountName
     * @return
     */
    @Override
    public int getAccountId(String userId, String accountName) {
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper
                .eq("user_id", userId)
                .eq("account_name", accountName)
                .select("account_id");
        Account account = accountMapper.selectOne(accountQueryWrapper);
        if (account != null){
            return account.getAccountId();
        }else {
            return 0;
        }
    }

    /**
     * 更新账户余额
     * @param accountId
     * @param updateSate
     * @param money
     * @return
     */
    @Override
    public int updateAccountMoney(int accountId, int updateSate, int money) {
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper
                .eq("account_id",accountId)
                .select("account_money");
        Account account = accountMapper.selectOne(accountQueryWrapper);
        int res = 0;
        if (account != null){
            if (updateSate == 1){
                int newMoney = account.getAccountMoney()-money;
                UpdateWrapper<Account> updateWrapper = new UpdateWrapper<>();
                updateWrapper
                        .eq("account_id", accountId)
                        .set("account_money", newMoney);
                res = accountMapper.update(null, updateWrapper);
            }else if (updateSate == 0){
                int newMoney = account.getAccountMoney()+money;
                UpdateWrapper<Account> updateWrapper = new UpdateWrapper<>();
                updateWrapper
                        .eq("account_id", accountId)
                        .set("account_money", newMoney);
                res = accountMapper.update(null, updateWrapper);
            }
        }
        return res;
    }

    /**
     * 获取账户名称
     * @param userId
     * @param accountId
     * @return
     */
    @Override
    public String getAccountName(String userId, int accountId) {
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper
                .eq("user_id", userId)
                .eq("account_id", accountId)
                .select("account_name");
        Account account = accountMapper.selectOne(accountQueryWrapper);
        return account.getAccountName();
    }

    /**
     * 获取账户余额
     * @param userId
     * @param accountId
     * @return
     */
    @Override
    public int getAccountMoney(String userId, int accountId) {
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper
                .eq("user_id", userId)
                .eq("account_id", accountId)
                .select("account_money");
        Account account = accountMapper.selectOne(accountQueryWrapper);
        return account.getAccountMoney();
    }

    /**
     * 获取某个账户的信息
     * @param userId
     * @param accountId
     * @return
     */
    @Override
    public Account getAccountInfo(String userId, int accountId) {
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper
                .eq("user_id", userId)
                .eq("account_id", accountId);
        Account account = accountMapper.selectOne(accountQueryWrapper);
        return account;
    }

    /**
     * 获取用户的总资产，净资产，负债，借出，借入
     * @param userId
     * @return
     */
    @Override
    public ResponseResult sumMoney(String userId) {
        //储蓄账户总金额
        Integer saveAccount = accountMapper.sumMoney(userId, 0);
        int save = 0;
        if (saveAccount != null){
            save = saveAccount.intValue();
        }
        //借贷账户总金额
        Integer borAccount = accountMapper.sumMoney(userId, 1);
        int bor = 0;
        if (borAccount != null){
            bor = borAccount.intValue();
        }
        //借出总金额
        int outflow = borrowService.sumBorrowMoney(userId, 1);
        //借入总金额
        int inflow = borrowService.sumBorrowMoney(userId,0);

        //负债=借贷+借入
        int liability = bor-inflow;
        //总资产=储蓄+借出
        int totalAssets = save+outflow;
        //净资产
        int netAssets = liability+totalAssets;
        Map<String, Object> data = new HashMap<>();
        data.put("totalAssets", totalAssets);
        data.put("netAssets", netAssets);
        data.put("liability", liability);
        data.put("inflow", inflow);
        data.put("outflow", outflow);
        return ResponseResult.okResult(data);
    }

    /**
     * 删除账户（删除收支相关联的信息和转账信息）
     * @param userId
     * @param accountId
     * @return
     */
    @Override
    public ResponseResult deleteAccount(String userId, int accountId) {
        int resBill = detailService.updateBillByAcc(userId, accountId);
        int resTran = transferService.delTransferByAcc(userId, accountId);
        UpdateWrapper<Account> accountUpdateWrapper = new UpdateWrapper<>();
        accountUpdateWrapper
                .eq("account_id", accountId)
                .eq("user_id", userId);
        int resAcc = accountMapper.delete(accountUpdateWrapper);
        if (resAcc != 0){
            return ResponseResult.okResult(200, "操作成功");
        }else {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "操作失败");
        }
    }

    @Autowired
    private DetailMapper detailMapper;
    @Autowired
    private BorrowMapper borrowMapper;
    @Autowired
    private TransferMapper transferMapper;

    /**
     * 获取账户余额，流入，流出
     * @param userId
     * @param accountId
     * @return
     */
    @Override
    public ResponseResult AllInOutflow(String userId, int accountId) {
        int inflow = 0;
        int outflow = 0;
        int accountMoney = getAccountMoney(userId, accountId);
        Map<String, Integer> res = new HashMap();
        res.put("accountMoney", accountMoney);

        QueryWrapper<Bill> billInQuery = new QueryWrapper<>();
        billInQuery
                .eq("user_id", userId)
                .eq("account_id", accountId)
                .eq("state", 0)
                .select("sum(money) money");
        Bill billInflow = detailMapper.selectOne(billInQuery);

        QueryWrapper<Borrow> borrowInQuery = new QueryWrapper<>();
        borrowInQuery
                .eq("user_id", userId)
                .eq("account_id", accountId)
                .eq("state", 0)
                .select("sum(borrow_money) borrowMoney");

        Borrow borrowInflow = borrowMapper.selectOne(borrowInQuery);

        QueryWrapper<Transfer> transferInQuery = new QueryWrapper<>();
        transferInQuery
                .eq("user_id", userId)
                .eq("from_id", accountId)
                .eq("transfer_state", 0)
                .select("sum(transfer_money) transferMoney");

        Transfer transferInflow = transferMapper.selectOne(transferInQuery);

        if (billInflow != null){
            inflow+=billInflow.getMoney();
        }
        if (borrowInflow != null){
            inflow+=borrowInflow.getBorrowMoney();
        }
        if (transferInflow != null){
            inflow+=transferInflow.getTransferMoney();
        }
        res.put("inflow", inflow);

        QueryWrapper<Bill> billOutQuery = new QueryWrapper<>();
        billOutQuery
                .eq("user_id", userId)
                .eq("account_id", accountId)
                .eq("state", 1)
                .select("sum(money) money");
        Bill billOutflow = detailMapper.selectOne(billOutQuery);

        QueryWrapper<Borrow> borrowOutQuery = new QueryWrapper<>();
        borrowOutQuery
                .eq("user_id", userId)
                .eq("account_id", accountId)
                .eq("state", 1)
                .select("sum(borrow_money) borrowMoney");

        Borrow borrowOutflow = borrowMapper.selectOne(borrowOutQuery);

        QueryWrapper<Transfer> transferOutQuery = new QueryWrapper<>();
        transferOutQuery
                .eq("user_id", userId)
                .eq("from_id", accountId)
                .eq("transfer_state", 1)
                .select("sum(transfer_money) transferMoney");

        Transfer transferOutflow = transferMapper.selectOne(transferOutQuery);

        if (billOutflow != null){
            outflow+=billOutflow.getMoney();
        }
        if (borrowOutflow != null){
            outflow+=borrowOutflow.getBorrowMoney();
        }
        if (transferOutflow != null){
            outflow+=transferOutflow.getTransferMoney();
        }
        res.put("outflow", outflow);

        return ResponseResult.okResult(res);
    }
}
